package com.lulin.mall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.lulin.common.constant.ProductConstant;
import com.lulin.mall.product.dao.AttrAttrgroupRelationDao;
import com.lulin.mall.product.dao.AttrGroupDao;
import com.lulin.mall.product.entity.AttrAttrgroupRelationEntity;
import com.lulin.mall.product.entity.AttrGroupEntity;
import com.lulin.mall.product.entity.CategoryEntity;
import com.lulin.mall.product.service.AttrAttrgroupRelationService;
import com.lulin.mall.product.service.AttrGroupService;
import com.lulin.mall.product.service.CategoryService;
import com.lulin.mall.product.vo.AttrGroupRelationVO;
import com.lulin.mall.product.vo.AttrResponseVO;
import com.lulin.mall.product.vo.AttrVO;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lulin.common.utils.PageUtils;
import com.lulin.common.utils.Query;
import com.lulin.mall.product.dao.AttrDao;
import com.lulin.mall.product.entity.AttrEntity;
import com.lulin.mall.product.service.AttrService;
import org.springframework.transaction.annotation.Transactional;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {

    @Autowired
    AttrAttrgroupRelationService attrAttrgroupRelationService;


    @Autowired
    AttrAttrgroupRelationDao attrAttrgroupRelationDao;

    @Autowired
    AttrGroupService attrGroupService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    AttrGroupDao attrGrouupDao;

    /**
     * 根据catelogId，查询规格参数信息
     *
     * @param params    分页的Map对象数据
     * @param catelogId 类目id
     * @return
     */
    @Override
    public PageUtils queryBasePage(Map<String, Object> params, Long catelogId, String attrType) {
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("attr_type", "base".equalsIgnoreCase(attrType) ? 1 : 0);

        //1、根据类别id查询
        if (catelogId != 0) {
            wrapper.eq("catelog_id", catelogId);
        }
        //2、根据key，模糊查询
        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)) {
            //and是连接，匿名内部类的方式
            wrapper.and((w) -> {
                w.eq("attr_id", key).or().like("attr_name", key);
            });
        }
        //3、分页查询
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), wrapper);

        //4、关联的 我们需要查询出类别名称 和属性组名称
        PageUtils pageUtils = new PageUtils(page);

        //拉倒结果集
        List<AttrEntity> resultList = page.getRecords();
        //流处理
        List<Object> list = resultList.stream().map((attrEntity) -> {
            //数组组的对象
            AttrResponseVO attrResponseVO = new AttrResponseVO();
            BeanUtils.copyProperties(attrEntity, attrResponseVO);

            //查询每一条结果，对应的类别名称和属性组名称
            CategoryEntity categoryEntity = categoryService.getById(attrEntity.getCatelogId());
            if (categoryEntity != null) {
                //设置类目的名称
                attrResponseVO.setCatelogName(categoryEntity.getName());
            }
            //如果attrType=0，是销售属性，才去属性组
            if ("base".equalsIgnoreCase(attrType)) {
                //设置属性组名称
                AttrAttrgroupRelationEntity entity = new AttrAttrgroupRelationEntity();
                entity.setAttrId(attrEntity.getAttrId());

                //1）去关联表中，查询对应的属性组id
                AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = attrAttrgroupRelationDao
                        .selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>()
                                .eq("attr_id", entity.getAttrId()));
                //2）查询出来后，进行判断
                if (attrAttrgroupRelationEntity != null && attrAttrgroupRelationEntity.getAttrGroupId() != null) {
                    //获取到属性组的ID，根据属性组的ID，来查询 属性组的名称
                    AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrAttrgroupRelationEntity.getAttrGroupId());
                    attrResponseVO.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }
            return attrResponseVO;
        }).collect(Collectors.toList());

        //更新pageUtils的list对象
        pageUtils.setList(list);
        return pageUtils;
    }

    /**
     * 根据规格参数ID查询对应的详细信息
     * 1.规格参数的具体信息——pms_attr表
     * 2.关联的属性组信息——关联表查-pms_attr_attrgroup_relation
     * 查询属性信息：attr_group
     * 3.关联的类别信息——类别表
     *
     * @param attrId 属性id
     * @return
     */
    @Override
    public AttrResponseVO getAttrInfo(Long attrId) {
        //声明返回的对象
        AttrResponseVO responseVO = new AttrResponseVO();

        //1、根据属性id，查询属性的基本信息
        AttrEntity attrEntity = this.getById(attrId);
        BeanUtils.copyProperties(attrEntity, responseVO);

        //2、查询关联的属性组信息——中间表
        //如果是基本属性，才有这些信息，如果是销售属性，就没有了
        if (attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
            AttrAttrgroupRelationEntity relationEntity = attrAttrgroupRelationDao.selectOne(
                    new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId));

            if (relationEntity != null) {
                //根据属性组id，查询属性组信息
                AttrGroupEntity attrGroupEntity = attrGroupService.getById(relationEntity.getAttrGroupId());
                responseVO.setAttrGroupId(attrGroupEntity.getAttrGroupId());
                if (attrGroupEntity != null) {
                    responseVO.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }
        }

        //3、查询关联的类别信息
        Long catelogId = attrEntity.getCatelogId();
        //根据类别编号查询出对应的父组件,找到对应的【一级、二级、三级】类目数据
        Long[] cateLogPath = categoryService.findCateLogPath(catelogId);
        responseVO.setCatelogPath(cateLogPath);

        //根据id，查询类别UI小，设置名称
        CategoryEntity categoryEntity = categoryService.getById(catelogId);
        if (categoryEntity != null) {
            responseVO.setCatelogName(categoryEntity.getName());
        }
        return responseVO;
    }

    /**
     * 更新属性的基本信息
     */
    @Transactional
    @Override
    public void updateBaseAttr(AttrVO attr) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr, attrEntity);

        //更新基本的信息
        this.updateById(attrEntity);

        if (attrEntity.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
            //更新属性分组的关联关联——关联表
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrId(attrEntity.getAttrId());
            relationEntity.setAttrGroupId(attr.getAttrGroupId());

            //判断是否存在独有的数据——根据属性id，去查询卡是否有记录
            Integer count = attrAttrgroupRelationDao.selectCount(
                    new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
            if (count > 0) {
                //说明有记录，直接更新
                attrAttrgroupRelationDao.update(relationEntity,
                        new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
            } else {
                //说明没记录，直接插入
                attrAttrgroupRelationDao.insert(relationEntity);
            }
        }
    }

    /**
     * 批量删除属性
     *
     * @param attrIds
     */
    @Transactional
    @Override
    public void removeByIdsDetails(Long[] attrIds) {
        //1、遍历出属性id，去关联表中查询，删掉关联表数据
        for (Long attrId : attrIds) {
            AttrEntity byId = getById(attrId);
            //如果传来的是基本属性-1
            if (byId != null && byId.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
                //删除关联表中的信息
                attrAttrgroupRelationDao.delete(new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId));
            }
        }
        //2、删除属性表中的数据
        this.removeByIds(Arrays.asList(attrIds));

    }

    /**
     * 根据属性组id，查询对应的信息
     *
     * @param attrgroupId
     * @return
     */
    @Override
    public List<AttrEntity> getRelationAttr(Long attrgroupId) {
        //1、根据属性组id查询关联表中的记录，拿到属性id
        List<AttrAttrgroupRelationEntity> list = attrAttrgroupRelationDao
                .selectList(new QueryWrapper<AttrAttrgroupRelationEntity>()
                        .eq("attr_group_id", attrgroupId));
        //根据属性id数组，获取对应数组表的信息
        List<AttrEntity> attrEntities = list.stream().map((entity) -> this.getById(entity.getAttrId()))
                //过滤掉为空的情况
                .filter(entity -> entity != null)
                .collect(Collectors.toList());
        return attrEntities;
    }

    /**
     * 解除属性组合基本属性的关联关系
     * ——也就是删除--属性组合关联表中的记录
     *
     * @param vos
     */
    @Override
    public void deleteRelation(AttrGroupRelationVO[] vos) {
        //将接收到数据的对象转为1个entity实体对象
        List<AttrAttrgroupRelationEntity> list = Arrays.asList(vos).stream()
                .map((item) -> {
                    AttrAttrgroupRelationEntity entity = new AttrAttrgroupRelationEntity();
                    BeanUtils.copyProperties(item, entity);
                    return entity;
                }).collect(Collectors.toList());

        //批量删除关联表中的数据
        attrAttrgroupRelationDao.removeBatchRelation(list);
    }

    /**
     * 根据属性id，查询出未被关联的属性信息
     * 1、查询出所有的属性信息；
     * 2、查询书当前属性组关联的属性信息；
     * 3、1中排除掉2中的属性，剩下的就是我们查询到的属性信息；
     *
     * @param params
     * @param attrgroupId
     * @return
     */
    @Override
    public PageUtils getNoAttrRelation(Map<String, Object> params, Long attrgroupId) {
        //1、去属性组中，查询当前属性组所在的类别id;
        AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrgroupId);
        //获取对应的类目id
        Long catelogId = attrGroupEntity.getCatelogId();

        //2、当前分组，只能关联本身的类别下 没有被其他分组关联的属性
        //2.1 先找到这个类别下的所有分组id集合——如下：通过255 找到6和7的属性组id集合信息
        //6	存储	2	手机内存	    2	225
        //7	屏幕	2	2	        2	225
        List<AttrGroupEntity> groupEntityList = attrGrouupDao.selectList(new QueryWrapper<AttrGroupEntity>()
                .eq("catelog_id", catelogId));
        //2.2 通过属性组id，去关联表中，获取属性组的id集合信息
        List<Long> groupIds = groupEntityList.stream().map((g) -> g.getAttrGroupId()).collect(Collectors.toList());

        //2.3 查询类别下所有属性组已经分配的属性信息
        List<AttrAttrgroupRelationEntity> relationEntities = attrAttrgroupRelationDao
                .selectList(new QueryWrapper<AttrAttrgroupRelationEntity>()
                        .in("attr_group_id", groupIds));
        List<Long> attrIds = relationEntities.stream().map((m) -> m.getAttrId()).collect(Collectors.toList());
        //2.4 根据类别id,查询所有属性信息，并排除上面已经分配的属性
        // 这其实就是需要查询出最终返回给调用者的信息了  分页  带条件查询
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>()
                .eq("catelog_id", catelogId)
                //基本属性，不需要查询销售属性的信息
                .eq("attr_type", ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());
        //添加排除的条件
        if (attrIds != null && attrIds.size() > 0) {
            //notIn：字段值在区间内。——如果属性id，不在查询的属性数组中
            wrapper.notIn("attr_id", attrIds);
        }

        //根据key，查询操作.
        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)) {
            wrapper.and((w) -> {
                w.eq("attr_id", key).or().like("attr_name", key);
            });
        }
        //分页查询对应的信息
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), wrapper);

        return new PageUtils(page);
    }

    /**
     * 通过属性id，查询可以检索的属性编号
     *
     * @param attrIds 属性id
     * @return
     */
    @Override
    public List<Long> selectSearchAttrIds(List<Long> attrIds) {
        List<AttrEntity> list = this.list(new QueryWrapper<AttrEntity>().in("attr_id", attrIds)
                .eq("search_type", 1));
        return list.stream().map(item -> {
            return item.getAttrId();
        }).collect(Collectors.toList());
    }

    /**
     * 保存规格参数信息
     *
     * @param attrVO 接收前端参数的vo对象
     */
    @Override
    public void saveAttr(AttrVO attrVO) {
        //1、 保存规格参数的信息
        AttrEntity attrEntity = new AttrEntity();
        //把从attrVO对象的参数，复制给attrEntity对象的参数
        BeanUtils.copyProperties(attrVO, attrEntity);
        this.save(attrEntity);

        //2、保存规格参数和属性组关联的信息
        if (attrVO.getAttrGroupId() != null && attrVO.getAttrType() == ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {
            //设置相关属性
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
            attrAttrgroupRelationEntity.setAttrId(attrEntity.getAttrId());
            attrAttrgroupRelationEntity.setAttrGroupId(attrVO.getAttrGroupId());
            //将关联的数据，保存到对应的关联表中
            attrAttrgroupRelationService.save(attrAttrgroupRelationEntity);
        }
    }


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }


}
